package com.ruoyi.ai.ws;

import cn.dev33.satoken.exception.SaTokenException;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.helper.LoginHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Slf4j
@Component
@ServerEndpoint("/ws/ma/chat/{token}")
public class ChatWebSocketManager {

    private Long userId;

    // concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<ChatWebSocketManager> webSockets = new CopyOnWriteArraySet<>();

    // 用来存在线连接用户信息
    private static ConcurrentHashMap<Long, Session> sessionPool = new ConcurrentHashMap<>();

    /**
     * 链接成功调用的方法
     *
     * @param session session
     * @param token   用户表示
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "token") String token) {
        log.info("ws token:{}", token);
        LoginUser loginUser = LoginHelper.getLoginUser(token);
        if (loginUser == null) {
            try {
                session.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            throw new SaTokenException("连接失败，无效Token：" + token);
        }
        session.setMaxIdleTimeout(60 * 60 * 1000);
        this.userId = loginUser.getUserId();
        webSockets.add(this);
        sessionPool.put(userId, session);
        log.info("【websocket消息】有新的连接，userId:{},连接列队:{}", userId, sessionPool.size());
    }

    /**
     * 链接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        try {
            webSockets.remove(this);
            sessionPool.remove(this.userId);
            log.info("【websocket消息】连接断开，总数为:" + webSockets.size());
        } catch (Exception e) {
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端消息
     */
    @OnMessage
    public void onMessage(String message) {
        log.info("【websocket消息】收到客户端消息:" + message);
        //sendOneMessage(userId, "收到消息：" + message);
    }

    /**
     * 发送错误时的处理
     *
     * @param session session
     * @param error   错误信息
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.info("【websocket消息】收到客户端出现错误:" + error);
    }

    /**
     * 此为单点消息
     *
     * @param userId
     * @param message
     */
    public void sendOneMessage(Long userId, String message) {
        log.info("向前端发送消息，userId:{},message::{}", userId,message);
        Session session = sessionPool.get(userId);
        if (session != null && session.isOpen()) {
            try {
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                log.error("【websocket消息】 单点消息发送异常: {}, userId is {}", e.getMessage(), userId);
            }
        } else {
            log.info("消息发送失败:userId:{},message:{}", userId,message);
        }
    }

}
